﻿using Microsoft.EntityFrameworkCore;

namespace FlexField.Metadata.EntityFrameworkCore
{
    /// <summary>
    /// Base class for the Entity Framework database context used for metadata.
    /// </summary>
    public class MetadataDbContext : MetadataDbContext<string>
    {
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        protected MetadataDbContext()
        {
        }

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="options"></param>
        public MetadataDbContext(DbContextOptions options) : base(options)
        {
        }
    }

    /// <summary>
    /// Base class for the Entity Framework database context used for metadata.
    /// </summary>
    /// <typeparam name="TKey">The type of the primary key for fields and entities.</typeparam>
    public class MetadataDbContext<TKey> : MetadataFieldContext<TKey> where TKey : IEquatable<TKey>
    {
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        protected MetadataDbContext()
        {
        }

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="options"></param>
        public MetadataDbContext(DbContextOptions options) : base(options)
        {
        }

        /// <summary>
        /// Gets or sets the <see cref="DbSet{TEntity}"/> of Data Types.
        /// </summary>
        public virtual DbSet<DataEntity<TKey>> DataEntities { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="DbSet{TEntity}"/> of Data Type Properties.
        /// </summary>
        public virtual DbSet<DataEntityProperty<TKey>> DataTypeProperties { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<DataEntity<TKey>>(b =>
            {
                b.HasKey(t => t.Id);
                b.HasIndex(t => t.NormalizedEntityName).HasDatabaseName("EntityNameIndex").IsUnique();
                b.ToTable("MetadataEntities");
                b.Property(t => t.ConcurrencyStamp).IsConcurrencyToken();
                b.Property(t => t.NormalizedEntityName).HasMaxLength(256).IsRequired();
                b.Property(t => t.EntityName).HasMaxLength(256);
                b.Property(t => t.DisplayName).HasMaxLength(256);
                b.HasMany(t => t.Properties).WithOne().HasForeignKey(p => p.EntityId).IsRequired();
                b.HasMany(t => t.Fields).WithOne().HasForeignKey(f => f.EntityId).IsRequired();
            });

            builder.Entity<DataEntityProperty<TKey>>(b =>
            {
                b.HasKey(p => new { p.EntityId, p.NormalizedPropertyName });
                b.Property(p => p.NormalizedPropertyName).HasMaxLength(256).IsRequired();
                b.Property(p => p.PropertyName).HasMaxLength(256);
                b.ToTable("MetadataEntityProperties");
            });
        }
    }
}